package www.xudan.android_ffmpeg.videoplayer.widget;

import android.app.Activity;
import android.app.Service;
import android.content.Context;
import android.graphics.Color;
import android.media.AudioManager;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;




import java.util.Date;
import java.util.Timer;

import tv.danmaku.ijk.media.player.IMediaPlayer;
import www.xudan.android_ffmpeg.R;
import www.xudan.android_ffmpeg.videoplayer.lifecyclemanager.ILifecycle;
import www.xudan.android_ffmpeg.videoplayer.model.VideoModel;
import www.xudan.android_ffmpeg.videoplayer.util.AnimUtil;
import www.xudan.android_ffmpeg.videoplayer.util.ProgressTimerTask;
import www.xudan.android_ffmpeg.videoplayer.util.Px2Dp;
import www.xudan.android_ffmpeg.videoplayer.util.TimeUtil;

abstract public class ControllerView extends BasePlayerView implements ILifecycle, View.OnClickListener, View.OnTouchListener, SeekBar.OnSeekBarChangeListener {
    protected LinearLayout vg_definition_list;
    protected TextView tv_definition;
    protected View controllerRoot;
    boolean showDefinitionView = false;//是否正在展示分辨率列表
    boolean isAniming = false;//是否正在执行动画，执行时屏蔽点击事件
    boolean showController = false;//是否正在执行动画，执行时屏蔽点击事件
    boolean shieldingTouch = false;//屏蔽触摸事件，一般在播放错误时
    protected LinearLayout ll_set_by_touch;
    protected ImageView iv_set_img_by_touch;
    protected ProgressBar pb_by_touch;
    protected TextView tv_seek_by_touch;
    int volume = 100;
    int luminance = 100;
    int touchStartX = 0;
    int touchStartY = 0;
    long touchStartTime = 0;
    private RelativeLayout rl_root;
    int touchSetKind = -1;
    public final int CLOSE_CONTROLLER = -122;
    protected final int TOUCHSETKINDVOLUME = 21;
    protected final int TOUCHSETKINDLUMINANCE = 22;
    protected final int TOUCHSETKINDSEKK = 23;
    protected String title;
    public Handler handler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            ControllerView.this.handleMessage(msg);
            return false;
        }
    });
    public TextView title_with_always;
    public TextView title_with_controller;
    public ImageView full_screen;
    public ImageView iv_video_pic;
    public ImageView iv_screen_play;
    public SeekBar seek_bar;
    public TextView tv_time;
    public Timer mProgressTimer;
    public ProgressTimerTask mProgressTimerTask;
    public ProgressBar loading;
    public ImageView seek_play;
    public boolean alwaysShow;
    public LinearLayout ll_controller;

    public ControllerView(Context context) {
        super(context);
    }

    public ControllerView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ControllerView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }


    protected void initView() {
        super.initView();
        controllerRoot = LayoutInflater.from(mContext).inflate(R.layout.media_controller_normal, null, false);
        addView(controllerRoot);
        full_screen = findViewById(R.id.full_screen);
        iv_video_pic = findViewById(R.id.iv_video_pic);
        iv_screen_play = findViewById(R.id.iv_screen_play);
        seek_bar = findViewById(R.id.seek_bar);
        tv_time = findViewById(R.id.tv_time);
        ll_controller = findViewById(R.id.ll_controller);
        seek_bar.setMax(100);
        seek_bar.setProgress(0);
        seek_bar.setOnSeekBarChangeListener(this);
        iv_screen_play.setOnClickListener(this);
        iv_video_pic.setClickable(false);
        seek_play = findViewById(R.id.seek_play);
        seek_play.setOnClickListener(this);
        vg_definition_list = findViewById(R.id.vg_definition_list);
        loading = findViewById(R.id.loading);
        tv_definition = findViewById(R.id.tv_definition);
        rl_root = findViewById(R.id.rl_root);
        title_with_always = findViewById(R.id.tv_title_with_always);
        title_with_controller = findViewById(R.id.tv_title_with_controller);
        tv_definition.setOnClickListener(this);
        ll_set_by_touch = findViewById(R.id.ll_set_by_touch);
        iv_set_img_by_touch = findViewById(R.id.iv_set_img_by_touch);
        pb_by_touch = findViewById(R.id.pb_by_touch);
        tv_seek_by_touch = findViewById(R.id.tv_seek_by_touch);
        controllerRoot.setOnTouchListener(this);
    }

    public void initVolume(int volume) {
        this.volume = volume;
    }

    public void initLuminance(int luminance) {
        this.luminance = luminance;
    }

    public ImageView getVideoPicImageView() {
        return iv_video_pic;
    }

    @Override
    public void onClick(View v) {
        if (isAniming)
            return;
        int id = v.getId();
        if (id == R.id.full_screen) {
            fullScreen();
            return;
        }
        if (id == R.id.tv_definition) {
            if (showDefinitionView) {
                closeDefinitionView();
            } else {
                showDefinitionView();
            }
        }
        if (id == R.id.iv_screen_play) {
            play();
        }
        if (id == R.id.seek_play) {
            play();
        }
    }

    protected void initDefinitionView() {
        if (videoModels != null && videoModels.size() > 0) {
            vg_definition_list.removeAllViews();
            vg_definition_list.setVisibility(GONE);
            for (final VideoModel videoModel : videoModels) {
                TextView textView = new TextView(getContext());
                textView.setText(videoModel.definitionName);
                textView.setHeight(Px2Dp.dip2px(getContext(), 35));
                textView.setWidth(Px2Dp.dip2px(getContext(), 60));
                textView.setTextSize(16);
                textView.setGravity(Gravity.CENTER);
                textView.setTextColor(Color.parseColor("#dddddd"));
                textView.setBackgroundColor(Color.parseColor("#33333333"));
                vg_definition_list.addView(textView);
                textView.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        switchDefinition(videoModel);
                        closeDefinitionView();
                    }
                });
            }
            vg_definition_list.setTranslationY(Px2Dp.dip2px(getContext(), 35) * videoModels.size());
            vg_definition_list.setAlpha(0.0f);
        }
    }

    public void setTitle(String title) {
        this.title = title;
        title_with_controller.setText(title);
        title_with_controller.setVisibility(VISIBLE);
        title_with_always.setVisibility(GONE);
    }

    public void setTitle(String title, boolean alwaysShow) {
        this.alwaysShow = alwaysShow;
        if (!alwaysShow) {
            setTitle(title);
        } else {
            this.title = title;
            title_with_always.setText(title);
            title_with_always.setVisibility(VISIBLE);
            title_with_controller.setVisibility(GONE);
        }
    }

    void showDefinitionView() {
        vg_definition_list.setVisibility(VISIBLE);
        int height = Px2Dp.dip2px(getContext(), 35);
        height = height * videoModels.size();
        final int finalHeight = height;
        AnimUtil.createAnimUtil(this, height, 0, 200, new AnimUtil.AnimListener() {
            @Override
            public void animUpdate(float value, int status) {
                if (status == -1) {
                    vg_definition_list.setTranslationY(value);
                    vg_definition_list.setAlpha((finalHeight - value) / finalHeight);
                } else {
                    isAniming = false;
                    vg_definition_list.setTranslationY(0);
                    vg_definition_list.setAlpha(1);
                }
            }
        }).start();
        isAniming = true;
        showDefinitionView = true;
    }

    void closeDefinitionView() {
        int height = Px2Dp.dip2px(getContext(), 35);
        height = height * videoModels.size();
        final int finalHeight = height;
        AnimUtil.createAnimUtil(this, 0, height, 200, new AnimUtil.AnimListener() {
            @Override
            public void animUpdate(float value, int status) {
                if (status == -1) {
                    vg_definition_list.setTranslationY(value);
                    vg_definition_list.setAlpha((finalHeight - value) / finalHeight);
                } else {
                    isAniming = false;
                    showDefinitionView = false;
                    vg_definition_list.setVisibility(GONE);
                    vg_definition_list.setTranslationY(finalHeight);
                    vg_definition_list.setAlpha(0);
                }
            }
        }).start();
        isAniming = true;
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (isAniming)
            return false;
        if (shieldingTouch)
            return false;
        if (player == null) {
            return false;
        }
        if (v.getId() == R.id.ll_controller) {
            return false;
        }
        int action = event.getAction();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                touchStartTime = new Date().getTime();
                touchStartX = (int) event.getX();
                touchStartY = (int) event.getY();
                touchSetKind = -1;
                break;
            case MotionEvent.ACTION_MOVE:
                if (new Date().getTime() - touchStartTime < 150)
                    return true;
                float x = event.getX();
                float y = event.getY();
                if (touchSetKind == -1) {
                    float absX = Math.abs(x - touchStartX);
                    float absY = Math.abs(y - touchStartY);
                    if (absX > absY * 2 / 3) {
                        touchSetKind = TOUCHSETKINDSEKK;
                    } else {
                        int width = getWidth() / 2;
                        if (touchStartX > width) {
                            touchSetKind = TOUCHSETKINDVOLUME;
                        } else {
                            touchSetKind = TOUCHSETKINDLUMINANCE;
                        }
                    }
                }
                switch (touchSetKind) {
                    case TOUCHSETKINDVOLUME:
                        setVolume((int) (touchStartY - y));
                        touchStartY = (int) y;
                        break;
                    case TOUCHSETKINDLUMINANCE:
                        setLuminance((int) (touchStartY - y));
                        touchStartY = (int) y;
                        break;
                    case TOUCHSETKINDSEKK:
                        adjustSeekByTouch((int) (x - touchStartX), false);
                        break;
                }
                break;
            case MotionEvent.ACTION_UP:
                if (new Date().getTime() - touchStartTime < 150) {
                    if (showController) {
                        closeController();
                    } else {
                        showController();
                    }
                } else {
                    if (touchSetKind == TOUCHSETKINDSEKK) {
                        adjustSeekByTouch((int) (event.getX() - touchStartX), true);
                    }
                    ll_set_by_touch.setVisibility(GONE);
                }
                break;
        }
        return true;
    }

    protected void showController() {
        rl_root.setAlpha(0.0f);
        rl_root.setVisibility(VISIBLE);
        AnimUtil.createAnimUtil(this, 0.0f, 1.0f, 200, new AnimUtil.AnimListener() {
            @Override
            public void animUpdate(float value, int status) {
                if (status == -1) {
                    rl_root.setAlpha(value);
                } else {
                    isAniming = false;
                    rl_root.setAlpha(1.0f);
                    handler.sendEmptyMessageDelayed(CLOSE_CONTROLLER, 3000);
                }
            }
        }).start();
        isAniming = true;
        showController = true;
    }

    public void closeController(boolean withAnim) {
        handler.removeMessages(CLOSE_CONTROLLER);
        if (withAnim) {
            AnimUtil.createAnimUtil(this, 1.0f, 0.0f, 200, new AnimUtil.AnimListener() {
                @Override
                public void animUpdate(float value, int status) {
                    if (status == -1) {
                        rl_root.setAlpha(value);
                    } else {
                        isAniming = false;
                        showController = false;
                        rl_root.setAlpha(0.0f);
                        rl_root.setVisibility(GONE);
                    }
                }
            }).start();
            isAniming = true;
        }else {
            isAniming = false;
            showController = false;
            rl_root.setAlpha(0.0f);
            rl_root.setVisibility(GONE);
        }
    }

    protected void closeController() {
        closeController(true);
    }

    void setVolume(int length) {
        int height = getHeight();
        ll_set_by_touch.setVisibility(VISIBLE);
        iv_set_img_by_touch.setImageResource(R.drawable.trumpet);
        volume = (length * 200 / height + volume);
        volume = volume > 100 ? 100 : volume < 0 ? 0 : volume;
        pb_by_touch.setProgress(volume);
        pb_by_touch.setVisibility(VISIBLE);
        tv_seek_by_touch.setVisibility(GONE);
        AudioManager mAudioManager = (AudioManager) getContext().getSystemService(Service.AUDIO_SERVICE);
        int mMaxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
        mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volume * mMaxVolume / 100, 0);
    }

    void setLuminance(int length) {
        int height = getHeight();
        ll_set_by_touch.setVisibility(VISIBLE);
        iv_set_img_by_touch.setImageResource(R.drawable.luminance);
        luminance = (length * 200 / height + luminance);
        luminance = luminance > 100 ? 100 : luminance < 0 ? 0 : luminance;
        pb_by_touch.setProgress(luminance);
        pb_by_touch.setVisibility(VISIBLE);
        tv_seek_by_touch.setVisibility(GONE);
        WindowManager.LayoutParams lpa = ((Activity) getContext()).getWindow().getAttributes();
        lpa.screenBrightness = ((float) luminance) / 100.0f;
        if (lpa.screenBrightness > 1.0f) {
            lpa.screenBrightness = 1.0f;
        } else if (lpa.screenBrightness < 0.01f) {
            lpa.screenBrightness = 0.01f;
        }
        ((Activity) getContext()).getWindow().setAttributes(lpa);

    }

    void adjustSeekByTouch(int length, boolean isHandle) {
        length = length / 2;
        int width = getWidth();
        float time = ((float) length) / ((float) width) * duration;
        float nowTime = playTime;
        nowTime = nowTime + time > duration ? duration : nowTime + time;
        ll_set_by_touch.setVisibility(VISIBLE);
        if (length > 0) {
            iv_set_img_by_touch.setImageResource(R.drawable.advance);
        } else {
            iv_set_img_by_touch.setImageResource(R.drawable.retreat);
        }
        pb_by_touch.setProgress(volume);
        pb_by_touch.setVisibility(GONE);
        tv_seek_by_touch.setVisibility(VISIBLE);
        String s1 = TimeUtil.MSEL2Hour((long) nowTime);
        String s2 = TimeUtil.MSEL2Hour(duration);
        tv_seek_by_touch.setText(s1 + "/" + s2);
        if (nowTime < 0) {
            nowTime = 0;
        }
        if (nowTime > duration) {
            nowTime = duration;
        }
        if (isHandle) {
            cancelProgressTimer();
            player.seekTo((long) nowTime);
            onProgressUpdate((long) nowTime, player.getDuration());
        }
    }

    private void handleMessage(Message msg) {
        switch (msg.what) {
            case CLOSE_CONTROLLER:
                closeController();
                break;
        }
    }

    @Override
    public void onSeekComplete(IMediaPlayer iMediaPlayer) {
        super.onSeekComplete(iMediaPlayer);
        seek_bar.setSecondaryProgress(0);
        startProgressTimer();
    }

    @Override
    public boolean onError(IMediaPlayer iMediaPlayer, int i, int i1) {
        super.onError(iMediaPlayer, i, i1);
        iv_screen_play.setImageResource(R.drawable.error);
        iv_screen_play.setVisibility(VISIBLE);
        if (showController) {
            closeController();
        }
        shieldingTouch = true;
        Toast.makeText(getContext(), "播放错误", Toast.LENGTH_SHORT).show();
        return false;
    }


    public void showLoading() {
        if (loading != null) {
            loading.setVisibility(VISIBLE);
        }
    }

    public void removeLoading() {
        if (loading != null) {
            loading.setVisibility(GONE);
        }
    }

    public void onCompletion(IMediaPlayer iMediaPlayer) {
        super.onCompletion(iMediaPlayer);
        seek_bar.setProgress(100);
        cancelProgressTimer();
    }

    @Override
    public void onBufferingUpdate(IMediaPlayer iMediaPlayer, int i) {
        if (i > 92) i = 100;
        seek_bar.setSecondaryProgress(i);
    }

    public void cancelProgressTimer() {
        if (mProgressTimerTask != null) {
            mProgressTimerTask.cancel();
        }
        if (mProgressTimer != null) {
            mProgressTimer.cancel();
        }
    }

    public void startProgressTimer() {
        cancelProgressTimer();
        mProgressTimer = new Timer();
        mProgressTimerTask = new ProgressTimerTask(this);
        mProgressTimer.schedule(mProgressTimerTask, 0, 300);
    }

    public void onProgressUpdate(final long position, final long duration) {
        this.duration = duration;
        this.playTime = position;
        post(new Runnable() {
            @Override
            public void run() {
                if (duration == 0) {
                    return;
                }
                int progress = (int) (position * 100 / duration);
                seek_bar.setProgress(progress);
                tv_time.setText(TimeUtil.MSEL2Hour(position) + "/" + TimeUtil.MSEL2Hour(duration));
            }
        });

    }

    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {

    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
        cancelProgressTimer();
    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
        player.seekTo(player.getDuration() / 100 * seekBar.getProgress());
        onProgressUpdate(player.getDuration() / 100 * seekBar.getProgress(), player.getDuration());
    }
}
